package utils

import (
	"errors"
	"gin-AssetManagement/inits/casbininit"
	"github.com/golang-jwt/jwt/v5"
	"strconv"
	"time"
)

type Myclaims struct {
	Username string
	UserId   uint
	RoleId   []uint `json:"role_id"`
	jwt.RegisteredClaims
}

const key = "woxiangtiyanavnv"

// MyCustomClaims 加密生成token
func MyCustomClaims(username string, usreID uint, roleId []uint) (token string, err error) {
	// Create a new Myclaims struct with the given username, userID, and roleID
	c := Myclaims{
		Username: username,
		UserId:   usreID,
		RoleId:   roleId,
		RegisteredClaims: jwt.RegisteredClaims{
			Issuer:    "GIn_admin_server",                                //颁发者，表示生成Token的实体。
			Subject:   "tang",                                            //主题，表示Token的主题。
			Audience:  jwt.ClaimStrings{"Android_APP", "IOS_APP", "WEB"}, //观众，表示Token的接收者。
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour)),     //过期时间，表示Token的有效期截止时间。应该是一个以秒为单位的时间戳。
			//NotBefore: jwt.NewNumericDate(time.Now().Add(time.Second)), //生效时间，表示Token在这个时间之前是无效的。应该是一个以秒为单位的时间戳。 不配置默认立即生效
			IssuedAt: jwt.NewNumericDate(time.Now()), //签发时间，表示Token的签发时间。应该是一个以秒为单位的时间戳。
			//JwtID:      "987654321",                                    //Token的JWT ID。

		},
	}
	token, err = jwt.NewWithClaims(jwt.SigningMethodHS256, c).SignedString([]byte(key))
	return token, err
}

// ParseTokenHs256 解密token
func ParseTokenHs256(token_string string) (*Myclaims, error) {
	//解析token字符串，并使用自定义的Myclaims类型进行验证
	token, err := jwt.ParseWithClaims(token_string, &Myclaims{}, func(token *jwt.Token) (interface{}, error) {
		return []byte(key), nil //返回签名密钥
	})
	if err != nil {
		return nil, err
	}

	//检查token是否有效
	if !token.Valid {
		return nil, errors.New("身份验证失败,token无效")
	}

	//断言成为Myclaims类型
	claims, ok := token.Claims.(*Myclaims)
	if !ok {
		return nil, errors.New("无效的索赔类型")
	}
	return claims, nil
}

var e = casbininit.Ecasbin

func IsRolesAcl(myclaims Myclaims, url, requestType string) bool {
	// s假设用户的角色列表为rolesLit，权限验证的对象为obj，操作为act
	if url == "/home/index" { // 首页不做认证
		return true
	}
	for _, role := range myclaims.RoleId {
		sub := strconv.Itoa(int(role))
		allowed, _ := e.Enforce(sub, url, requestType)
		if allowed {
			// 只要其中一个角色有权限，即可认为用户有权限
			return true
		}
	}
	// 所有角色都没有权限
	return false

}
